﻿using BLevy.Datos.Interfases;
using BLevy.Entidad;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using MySql.Data.MySqlClient;
using System.Configuration;
using Dapper;
using DapperExtensions;

namespace BLevy.Datos.Repositories
{
    public interface IPeriodoSocioRepository : IRepository<PeriodoSocio>
    {
        double CalcularCuota(Socio socio);
        IList<PeriodoSocio> FindAllImpagosBySocioId(int socio_id);
    }

    public class PeriodoSocioRepository : IPeriodoSocioRepository
    {
        protected readonly IDbConnection _db;

        public PeriodoSocioRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<PeriodoSocio> FindAll()
        {
            string query = "SELECT * FROM PERIODOSSOCIOS";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<PeriodoSocio>(query).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IQueryable<PeriodoSocio> Find(System.Linq.Expressions.Expression<Func<PeriodoSocio, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public PeriodoSocio FindById(int id)
        {
            string query = "SELECT * FROM PERIODOSSOCIOS WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<PeriodoSocio>(query, new { id = id }).SingleOrDefault();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Add(PeriodoSocio newEntity)
        {
            string query = "INSERT INTO PERIODOSSOCIOS (PERIODO_ID, SOCIO_ID, IMPORTE, ESTADO) " +
                "VALUES (@periodo, @socio, @importe, @estado)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        periodo = newEntity.periodo_id,
                        socio = newEntity.socio_id,
                        importe = newEntity.importe,
                        estado = newEntity.estado
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Remove(int id)
        {
            throw new NotImplementedException();
        }

        public int Modify(PeriodoSocio entity)
        {
            throw new NotImplementedException();
        }

        public double CalcularCuota(Socio socio)
        {

            try
            {
                Datos.Repositories.PlanRepository planRepository = new PlanRepository();

                Plan _plan = planRepository.FindById(socio.plan_id);
                IList<AdicionalPlan> adicionalesPlanL = planRepository.FindAdicionalesByPlan(_plan.id);

                double cuota = 0;
                TimeSpan span = new TimeSpan();

                int hijos = 0;
                int otros = 0;

                cuota += _plan.costo_base;

                if (adicionalesPlanL != null)
                {
                    span = DateTime.Now.Date - socio.fecha_nacimiento;
                    int edad_socio = (int)Math.Truncate(span.TotalDays / 365.25);
                    if (edad_socio > _plan.edad_titular)
                    {
                        cuota += adicionalesPlanL.Where(adicional => adicional.edad_desde <= edad_socio && adicional.edad_hasta >= edad_socio).Select(adicional => adicional.costo_adicional).Single();
                    }
                    foreach (var adherente in socio.adherentes)
                    {
                        if (adherente.parentesco == "C")
                        {
                            span = DateTime.Now.Date - adherente.fecha_nacimiento;
                            int edad_conyuge = (int)Math.Truncate(span.TotalDays / 365.25);

                            if (_plan.conyuge == 1)
                            {
                                if (edad_conyuge > _plan.edad_conyuge)
                                {
                                    cuota += adicionalesPlanL.Where(adicional => adicional.edad_desde <= edad_conyuge && adicional.edad_hasta >= edad_conyuge).Select(adicional => adicional.costo_adicional).Single();
                                }
                            }
                            else
                            {
                                cuota += adicionalesPlanL.Where(adicional => adicional.edad_desde <= edad_conyuge && adicional.edad_hasta >= edad_conyuge).Select(adicional => adicional.costo_adicional).Single();
                            }

                        }
                        else if (adherente.parentesco == "H")
                        {
                            span = DateTime.Now.Date - adherente.fecha_nacimiento;
                            int edad_hijo = (int)Math.Truncate(span.TotalDays / 365.25);

                            if (_plan.hijos == 1 && _plan.cantidad_hijos > hijos)
                            {
                                if (edad_hijo > _plan.edad_hijos)
                                {
                                    cuota += adicionalesPlanL.Where(adicional => adicional.edad_desde <= edad_hijo && adicional.edad_hasta >= edad_hijo).Select(adicional => adicional.costo_adicional).Single();
                                }
                                else
                                {
                                    hijos++;
                                }
                            }
                            else
                            {
                                cuota += adicionalesPlanL.Where(adicional => adicional.edad_desde <= edad_hijo && adicional.edad_hasta >= edad_hijo).Select(adicional => adicional.costo_adicional).Single();
                            }
                        }
                        else
                        {
                            span = DateTime.Now.Date - adherente.fecha_nacimiento;
                            int edad_otro = (int)Math.Truncate(span.TotalDays / 365.25);

                            if (_plan.otros == 1 && _plan.cantidad_otros > otros)
                            {
                                if (edad_otro > _plan.edad_otros)
                                {
                                    cuota += adicionalesPlanL.Where(adicional => adicional.edad_desde <= edad_otro && adicional.edad_hasta >= edad_otro).Select(adicional => adicional.costo_adicional).Single();
                                }
                                else
                                {
                                    otros++;
                                }
                            }
                            else
                            {
                                cuota += adicionalesPlanL.Where(adicional => adicional.edad_desde <= edad_otro && adicional.edad_hasta >= edad_otro).Select(adicional => adicional.costo_adicional).Single();
                            }
                        }
                    }
                }

                return cuota;
            }
            catch(Exception e)
            {
                throw e;
            }
           
        }

        public IList<PeriodoSocio> FindAllImpagosBySocioId(int socio_id)
        {
            string query = "SELECT * FROM PERIODOSSOCIOS " +
                            "WHERE SOCIO_ID = @socio_id AND estado = @estado";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<PeriodoSocio>(query, new { socio_id = socio_id, estado = "I" }).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }
    }
}
